package com.hzw.saas.service.property.service;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.property.IPropertyService;
import com.hzw.saas.api.property.bo.PropertyBO;
import com.hzw.saas.api.property.enmus.SysParamKeyEnum;
import com.hzw.saas.api.property.query.PropertyAddQuery;
import com.hzw.saas.api.property.query.PropertyUpdateQuery;
import com.hzw.saas.common.config.util.MybatisPlusUtil;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.ObjFieldUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.property.enums.ModuleEnum;
import com.hzw.saas.service.property.mapper.SysParamMapper;
import com.hzw.saas.service.property.model.SysParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author zzl
 * @since 09/13/2021
 */
@Service(IPropertyService.SYS_PARAM_BEAN)
@RequiredArgsConstructor
@Slf4j
public class SysParamServiceImpl extends ServiceImpl<SysParamMapper, SysParam> implements IPropertyService<SysParamKeyEnum>, IService<SysParam> {

    public static final String CACHE_GROUP = "sys:param";

    @Resource(name = IPropertyService.SYS_PARAM_BEAN)
    private IPropertyService<SysParamKeyEnum> self;

    @Override
    public PropertyBO getProperty(String id) {
        SysParam entity = super.getById(id);
        return MapperUtil.nf().map(entity, PropertyBO.class);
    }

    @Override
    public PropertyBO getProperty(String module, String key) {
        LambdaQueryChainWrapper<SysParam> query = super.lambdaQuery()
            .eq(SysParam::getModule, module)
            .eq(SysParam::getKey, key);
        MybatisPlusUtil.limitOne(query);
        SysParam entity = query.one();
        return MapperUtil.nf().map(entity, PropertyBO.class);
    }

    @Override
    public PropertyBO getProperty(SysParamKeyEnum key) {
        if (Objects.isNull(key)) {
            return null;
        }
        return self.getProperty(key.getModule(), key.getKey());
    }

    @Override
    @Cacheable(cacheNames = CACHE_GROUP, key = "#module+':'+#key")
    public String getPropertyValue(String module, String key) {
        Optional<PropertyBO> property = Optional.ofNullable(this.getProperty(module, key));
        return property.map(PropertyBO::getValue).orElse("");
    }

    @Override
    public String getPropertyValue(SysParamKeyEnum key) {
        if (Objects.isNull(key)) {
            return null;
        }
        return self.getPropertyValue(key.getModule(), key.getKey());
    }

    @Override
    public String getPropertyValue(String module, String key, String defaultValue) {
        String value = self.getPropertyValue(module, key);
        return StrUtil.isBlank(value) ? defaultValue : value;
    }

    @Override
    public String getPropertyValue(SysParamKeyEnum key, String defaultValue) {
        if (Objects.isNull(key)) {
            return defaultValue;
        }
        String value = self.getPropertyValue(key.getModule(), key.getKey());
        return StrUtil.isBlank(value) ? defaultValue : value;
    }

    @Override
    public List<PropertyBO> listProperties(String module) {
        List<SysParam> list = super.lambdaQuery()
            .eq(StrUtil.isNotBlank(module), SysParam::getModule, module)
            .list();
        return MapperUtil.nf().mapAsList(list, PropertyBO.class);
    }

    @Override
    public PropertyBO addProperty(PropertyAddQuery query) {
        Assert.notBlank(query.getModule(), "参数模块不可为空");
        Assert.notBlank(query.getKey(), "参数key不可为空");
        // 检查唯一性
        int count = super.lambdaQuery()
            .eq(SysParam::getModule, query.getModule())
            .eq(SysParam::getKey, query.getKey())
            .count();
        Assert.isTrue(count == 0, "已存在module和key");

        SysParam entity = MapperUtil.nf().map(query, SysParam.class);
        entity.setPid(SnowFlakeUtil.nextIdStr());
        if (Objects.isNull(entity.getStatus())) {
            entity.setStatus(1);
        }
        super.save(entity);
        return MapperUtil.nf().map(entity, PropertyBO.class);
    }

    @Override
    @CacheEvict(cacheNames = CACHE_GROUP)
    public boolean updateProperty(PropertyUpdateQuery query) {
        Assert.notBlank(query.getPid(), "pid为空");
        String pid = query.getPid();
        query.setPid(null);
        boolean allNullFields = ObjFieldUtil.isAllNullFields(query, ObjFieldUtil.ConvertNull.BLANK);
        Assert.isFalse(allNullFields, "无有效的待更新属性值");

        SysParam entity = MapperUtil.nf().map(query, SysParam.class);
        entity.setPid(pid);
        return super.updateById(entity);
    }

    @Override
    public List<PropertyBO> getWechatAttribute(String type) {
        if (StrUtil.isBlank(type)){
            List<SysParam> list = this.lambdaQuery().like(SysParam::getModule, "wechat." + "%").list();
            return MapperUtil.nf().mapAsList(list,PropertyBO.class);
        }
        String module = ModuleEnum.getDataByCode(type);
        List<SysParam> list = this.lambdaQuery().eq(SysParam::getModule, module).list();
        return MapperUtil.nf().mapAsList(list,PropertyBO.class);
    }
}
